{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE InstanceSigs #-}

module DataType
  ( TaskStatus(..)
  , SubTask(..)
  , Task(..)
  , AppData(..)

  -- * Lenses
  , subDoneL
  , subNameL
  , taskStatusL
  , urgentL
  , importantL
  , nameL
  , descL
  , createAtL
  , scheduleAtL
  , deadlineAtL
  , closeAtL
  , subTasksL
  , doTasksL
  , scheduleTasksL
  , delegateTasksL
  , eliminateTasksL

  -- * empty data constructors
  , emptyTask
  , emptyAppData

  -- * utilities
  , withPriority
  ) where

import Brick.Types (suffixLenses)
import Data.Text (Text)
import qualified Data.Time as Time
import qualified Data.Vector as V
import Data.Aeson.TH (deriveJSON, defaultOptions)

-- | Task status for main task object.
data TaskStatus = Todo
                | Done
                deriving (Show, Eq)

$(deriveJSON defaultOptions ''TaskStatus)

-- | Sub task for main task object.
data SubTask = SubTask { subDone :: Bool
                       , subName :: Text
                       }
             deriving (Show)

suffixLenses ''SubTask
$(deriveJSON defaultOptions ''SubTask)

instance Semigroup SubTask where
  -- | Merge tow sub tasks into one
  (<>) :: SubTask -> SubTask -> SubTask
  SubTask d1 n1 <> SubTask d2 n2 =
    SubTask (d1 && d2) (n1 <> "/" <> n2)

instance Monoid SubTask where
  -- | Create an empty sub task
  mempty :: SubTask
  mempty = SubTask False mempty

-- | Main task type
data Task = Task { taskStatus :: TaskStatus
                 -- ^ Current task status
                 , urgent :: Bool
                 -- ^ If the task if urgent
                 , important :: Bool
                 -- ^ If the task is important
                 , name :: Text
                 -- ^ Name of the task
                 , desc :: Text
                 -- ^ More description of the task
                 , createAt :: Maybe Time.LocalTime
                 -- ^ Time the task created
                 , scheduleAt :: Maybe Time.LocalTime
                 -- ^ Time the task should start at
                 , deadlineAt :: Maybe Time.LocalTime
                 -- ^ Time the task should be done
                 , closeAt :: Maybe Time.LocalTime
                 -- ^ Time the task closed
                 , subTasks :: V.Vector SubTask
                 -- ^ Sub task List of main task
                 }
          deriving (Show)

suffixLenses ''Task
$(deriveJSON defaultOptions ''Task)

-- | App data of agenda. All tasks are saved as 4 task lists
data AppData = AppData { doTasks :: V.Vector Task
                       , scheduleTasks :: V.Vector Task
                       , delegateTasks :: V.Vector Task
                       , eliminateTasks :: V.Vector Task
                       }

suffixLenses ''AppData
$(deriveJSON defaultOptions ''AppData)

emptyTask :: Task
emptyTask = Task { taskStatus = Todo
                 , urgent = False
                 , important = False
                 , name = ""
                 , desc = ""
                 , createAt = Nothing
                 , scheduleAt = Nothing
                 , deadlineAt = Nothing
                 , closeAt = Nothing
                 , subTasks = V.empty
                 }

emptyAppData :: AppData
emptyAppData =
  AppData { doTasks = V.empty
          , scheduleTasks = V.empty
          , delegateTasks = V.empty
          , eliminateTasks = V.empty
          }

-- | Update urgent and important field of task
withPriority :: Bool -> Bool -> Task -> Task
withPriority u c t =
  t { urgent = u
    , important = c
    }

